from flask import Flask, request, jsonify, render_template_string
import json
import threading
import time
from tcp_client import TCPClient

app = Flask(__name__)

# 全局TCP客户端实例
tcp_client = None
client_lock = threading.Lock()
tcp_server_available = False

def get_tcp_client():
    """获取TCP客户端实例（线程安全）"""
    global tcp_client, tcp_server_available
    with client_lock:
        if tcp_client is None or not tcp_client.connected:
            print("🔄 创建新的TCP客户端连接...")
            tcp_client = TCPClient('localhost', 8080)
            if tcp_client.connect():
                tcp_server_available = True
                print("✅ TCP服务器可用")
                return tcp_client
            else:
                tcp_server_available = False
                print("❌ TCP服务器不可用")
                return None
        return tcp_client

def create_mock_suggestions(keyword):
    """创建模拟建议数据"""
    if not keyword:
        return []
    
    base_suggestions = [
        f"{keyword} 教程",
        f"{keyword} 文档", 
        f"{keyword} 使用方法",
        f"{keyword} 最佳实践",
        f"{keyword} 示例代码"
    ]
    
    # 根据关键词长度调整建议数量
    if len(keyword) > 3:
        base_suggestions.extend([
            f"{keyword} 高级技巧",
            f"{keyword} 常见问题"
        ])
    
    return base_suggestions[:5]  # 最多返回5个建议

def create_mock_results(keyword):
    """创建模拟搜索结果"""
    if not keyword:
        return []
    
    return [
        {
            "id": 1,
            "title": f"关于 {keyword} 的完整指南",
            "link": f"https://example.com/{keyword}-guide",
            "abstract": f"这是一篇关于 {keyword} 的详细指南，涵盖了基本概念和高级用法。"
        },
        {
            "id": 2,
            "title": f"{keyword} 入门教程",
            "link": f"https://example.com/{keyword}-tutorial",
            "abstract": f"学习 {keyword} 的基础知识，适合初学者。"
        },
        {
            "id": 3,
            "title": f"{keyword} 最佳实践",
            "link": f"https://example.com/{keyword}-best-practices", 
            "abstract": f"了解在使用 {keyword} 时的最佳实践和常见陷阱。"
        }
    ]

# HTML模板
HTML_TEMPLATE = '''
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>搜索系统问题诊断</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            color: #333;
            line-height: 1.6;
            min-height: 100vh;
            padding: 20px;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        header {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 10px;
            padding: 25px 30px;
            text-align: center;
            margin-bottom: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }
        
        h1 {
            color: #1a2a6c;
            margin-bottom: 10px;
            font-size: 32px;
        }
        
        .subtitle {
            color: #b21f1f;
            font-size: 18px;
            font-weight: 500;
        }
        
        .dashboard {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 25px;
            margin-bottom: 25px;
        }
        
        .card {
            background: rgba(255, 255, 255, 0.95);
            border-radius: 10px;
            padding: 25px;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
        }
        
        .card-full {
            grid-column: 1 / -1;
        }
        
        .card h2 {
            color: #1a2a6c;
            margin-bottom: 20px;
            padding-bottom: 10px;
            border-bottom: 2px solid #f0f0f0;
            display: flex;
            align-items: center;
        }
        
        .card h2 i {
            margin-right: 10px;
            color: #b21f1f;
        }
        
        .status-grid {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 15px;
        }
        
        .status-item {
            text-align: center;
            padding: 20px 15px;
            background: #f8f9fa;
            border-radius: 8px;
            transition: transform 0.3s;
        }
        
        .status-item:hover {
            transform: translateY(-5px);
        }
        
        .status-value {
            font-size: 28px;
            font-weight: bold;
            margin: 10px 0;
        }
        
        .status-good {
            color: #28a745;
        }
        
        .status-warning {
            color: #ffc107;
        }
        
        .status-error {
            color: #dc3545;
        }
        
        .log-entry {
            padding: 15px;
            margin-bottom: 15px;
            background: #f8f9fa;
            border-radius: 8px;
            border-left: 4px solid #1a2a6c;
        }
        
        .log-time {
            color: #6c757d;
            font-size: 14px;
            margin-bottom: 5px;
        }
        
        .log-message {
            font-family: monospace;
            white-space: pre-wrap;
            margin-bottom: 5px;
        }
        
        .log-highlight {
            background-color: #fff3cd;
            padding: 2px 4px;
            border-radius: 3px;
            font-weight: bold;
        }
        
        .problem-section {
            margin-top: 20px;
            padding: 15px;
            background: #fff3cd;
            border-radius: 8px;
            border-left: 4px solid #ffc107;
        }
        
        .problem-title {
            font-weight: bold;
            margin-bottom: 10px;
            color: #856404;
        }
        
        .suggestion-box {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin-top: 15px;
        }
        
        .suggestion-item {
            padding: 8px 15px;
            background: #e9ecef;
            border-radius: 20px;
            font-size: 14px;
        }
        
        .suggestion-item.error {
            background: #f8d7da;
            color: #721c24;
        }
        
        .search-preview {
            margin-top: 20px;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 8px;
        }
        
        .search-box {
            display: flex;
            margin-bottom: 15px;
        }
        
        .search-input {
            flex: 1;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 4px 0 0 4px;
            font-size: 16px;
        }
        
        .search-button {
            background: #1a2a6c;
            color: white;
            border: none;
            padding: 0 20px;
            border-radius: 0 4px 4px 0;
            cursor: pointer;
            font-weight: bold;
        }
        
        .suggestions-preview {
            background: white;
            border: 1px solid #ddd;
            border-radius: 4px;
            padding: 10px;
            margin-top: 10px;
            min-height: 100px;
        }
        
        .suggestion-preview-item {
            padding: 8px 12px;
            border-bottom: 1px solid #f0f0f0;
            cursor: pointer;
        }
        
        .suggestion-preview-item:hover {
            background: #f8f9fa;
        }
        
        .suggestion-preview-item.error {
            color: #dc3545;
            font-weight: bold;
        }
        
        footer {
            text-align: center;
            padding: 20px;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 10px;
            color: #6c757d;
            margin-top: 25px;
        }
        
        @media (max-width: 768px) {
            .dashboard {
                grid-template-columns: 1fr;
            }
            
            .status-grid {
                grid-template-columns: 1fr;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1>搜索系统问题诊断</h1>
            <div class="subtitle">基于TCP协议的分布式搜索解决方案 - 问题分析与修复</div>
        </header>
        
        <div class="dashboard">
            <div class="card">
                <h2><i class="fas fa-heartbeat"></i> 系统状态概览</h2>
                <div class="status-grid">
                    <div class="status-item">
                        <div>服务状态</div>
                        <div class="status-value status-good">正常</div>
                        <div>HTTP 200 响应正常</div>
                    </div>
                    
                    <div class="status-item">
                        <div>响应时间</div>
                        <div class="status-value status-good">0.06s</div>
                        <div>搜索响应迅速</div>
                    </div>
                    
                    <div class="status-item">
                        <div>数据问题</div>
                        <div class="status-value status-error">严重</div>
                        <div>建议数据异常</div>
                    </div>
                </div>
            </div>
            
            <div class="card">
                <h2><i class="fas fa-search"></i> 搜索性能</h2>
                <div class="status-grid">
                    <div class="status-item">
                        <div>搜索结果</div>
                        <div class="status-value status-good">1748 条</div>
                        <div>查询"测试"</div>
                    </div>
                    
                    <div class="status-item">
                        <div>搜索耗时</div>
                        <div class="status-value status-good">0.06s</div>
                        <div>性能优秀</div>
                    </div>
                    
                    <div class="status-item">
                        <div>建议响应</div>
                        <div class="status-value status-good">0.00s</div>
                        <div>响应迅速</div>
                    </div>
                </div>
            </div>
            
            <div class="card card-full">
                <h2><i class="fas fa-exclamation-triangle"></i> 核心问题分析</h2>
                
                <div class="problem-section">
                    <div class="problem-title">搜索建议数据质量问题</div>
                    <p>系统搜索功能正常，但搜索建议返回的数据存在严重质量问题。当用户输入"中国"时，系统返回的建议词为：["三国","中盖","人国","中呢","中到"]，这些建议词与输入词"中国"语义关联性较弱，无法提供有效的搜索引导。</p>
                </div>
                
                <div class="log-entry">
                    <div class="log-time">[13/Nov/2025 22:27:06]</div>
                    <div class="log-message">🔍 获取搜索建议: '中国'
📤 发送消息: tag=1, length=6, value='中国'
✅ 消息发送成功
📥 开始接收响应...
📋 解析头: tag=1, expected_length=62
✅ 成功接收响应: length=62, value='{"suggestions":["三国","中盖","人国","中呢","中到"]}'
✅ 收到建议响应: 1 条建议, 耗时: 0.00s</div>
                    <div class="log-highlight">问题: 建议词与输入词语义相关性弱，无法提供有效的搜索引导</div>
                </div>
                
                <div class="log-entry">
                    <div class="log-time">[13/Nov/2025 22:27:20]</div>
                    <div class="log-message">🔍 获取搜索建议: '测试'
📤 发送消息: tag=1, length=6, value='测试'
✅ 消息发送成功
📥 开始接收响应...
📋 解析头: tag=1, expected_length=59
✅ 成功接收响应: length=59, value='{"suggestions":["面试","试试","测量","试","尝试"]}'
✅ 收到建议响应: 1 条建议, 耗时: 0.00s</div>
                    <div class="log-highlight">问题: 部分建议词相关性尚可，但"试"作为单字建议价值有限</div>
                </div>
                
                <h3 style="margin-top: 20px;">搜索建议预览</h3>
                <div class="search-preview">
                    <div class="search-box">
                        <input type="text" class="search-input" value="中国" readonly>
                        <button class="search-button">搜索</button>
                    </div>
                    
                    <div class="suggestions-preview">
                        <div class="suggestion-preview-item error">三国 (相关性: 弱)</div>
                        <div class="suggestion-preview-item error">中盖 (相关性: 弱)</div>
                        <div class="suggestion-preview-item error">人国 (相关性: 弱)</div>
                        <div class="suggestion-preview-item error">中呢 (相关性: 弱)</div>
                        <div class="suggestion-preview-item error">中到 (相关性: 弱)</div>
                    </div>
                    
                    <div style="margin-top: 15px; color: #dc3545; font-weight: bold;">
                        <i class="fas fa-exclamation-circle"></i> 当前问题：搜索建议词与输入词相关性弱，无法提供有效的搜索引导
                    </div>
                </div>
            </div>
            
            <div class="card">
                <h2><i class="fas fa-tools"></i> 问题根源</h2>
                <ul style="padding-left: 20px; margin-top: 15px;">
                    <li style="margin-bottom: 10px;">建议算法可能基于字符匹配而非语义理解</li>
                    <li style="margin-bottom: 10px;">词库质量不足或未更新</li>
                    <li style="margin-bottom: 10px;">缺少用户行为数据优化建议</li>
                    <li style="margin-bottom: 10px;">可能使用了不适当的相似度算法</li>
                </ul>
            </div>
            
            <div class="card">
                <h2><i class="fas fa-lightbulb"></i> 解决方案</h2>
                <ul style="padding-left: 20px; margin-top: 15px;">
                    <li style="margin-bottom: 10px;">引入基于语义理解的建议算法</li>
                    <li style="margin-bottom: 10px;">更新和优化建议词库</li>
                    <li style="margin-bottom: 10px;">集成用户搜索行为数据分析</li>
                    <li style="margin-bottom: 10px;">实现A/B测试验证建议效果</li>
                    <li style="margin-bottom: 10px;">添加建议词相关性评分机制</li>
                </ul>
            </div>
        </div>
        
        <footer>
            <p>© 2025 分布式搜索系统 | 问题诊断页面 | 最后更新: 2025-11-13 22:27:33</p>
        </footer>
    </div>

    <script>
        // 添加简单的交互效果
        document.addEventListener('DOMContentLoaded', function() {
            const statusItems = document.querySelectorAll('.status-item');
            
            statusItems.forEach(item => {
                item.addEventListener('click', function() {
                    this.style.transform = 'scale(0.95)';
                    setTimeout(() => {
                        this.style.transform = '';
                    }, 150);
                });
            });
            
            // 模拟搜索建议点击效果
            const suggestionItems = document.querySelectorAll('.suggestion-preview-item');
            suggestionItems.forEach(item => {
                item.addEventListener('click', function() {
                    if(this.classList.contains('error')) {
                        this.style.backgroundColor = '#f8d7da';
                        setTimeout(() => {
                            this.style.backgroundColor = '';
                        }, 500);
                    }
                });
            });
        });
    </script>
</body>
</html>
'''

@app.route('/')
def index():
    """提供搜索页面"""
    return render_template_string(HTML_TEMPLATE)

@app.route('/suggest', methods=['POST'])
def get_suggestions():
    """获取搜索建议"""
    data = request.get_json()
    keyword = data.get('keyword', '')
    
    if not keyword:
        return jsonify({'suggestions': []})
    
    print(f"🔍 获取搜索建议: '{keyword}'")
    
    # 获取TCP客户端
    client = get_tcp_client()
    if not client:
        # TCP服务器不可用，返回模拟数据
        print("⚠️ TCP服务器不可用，返回模拟建议")
        suggestions = create_mock_suggestions(keyword)
        return jsonify({'suggestions': suggestions})
    
    # 发送关键字建议请求到TCP服务器 (tag=1)
    start_time = time.time()
    response = client.send_message(1, keyword)
    elapsed_time = time.time() - start_time
    
    if response and response['tag'] == 1:
        try:
            suggestions = json.loads(response['value'])
            print(f"✅ 收到建议响应: {len(suggestions)} 条建议, 耗时: {elapsed_time:.2f}s")
            return jsonify({'suggestions': suggestions})
        except Exception as e:
            print(f"❌ 解析建议数据失败: {e}")
            # 返回模拟数据作为备选
            suggestions = create_mock_suggestions(keyword)
            return jsonify({'suggestions': suggestions})
    
    # 如果TCP服务器无响应，返回模拟数据
    print(f"⚠️ TCP服务器无响应，返回模拟建议，耗时: {elapsed_time:.2f}s")
    suggestions = create_mock_suggestions(keyword)
    return jsonify({'suggestions': suggestions})

@app.route('/search', methods=['POST'])
def search():
    """执行搜索"""
    data = request.get_json()
    keyword = data.get('keyword', '')
    
    if not keyword:
        return jsonify({'results': []})
    
    print(f"🔍 执行搜索: '{keyword}'")
    
    # 获取TCP客户端
    client = get_tcp_client()
    if not client:
        # TCP服务器不可用，返回模拟数据
        print("⚠️ TCP服务器不可用，返回模拟结果")
        results = create_mock_results(keyword)
        return jsonify({'results': results})
    
    # 发送搜索请求到TCP服务器 (tag=2)
    start_time = time.time()
    response = client.send_message(2, keyword)
    elapsed_time = time.time() - start_time
    
    if response and response['tag'] == 2:
        try:
            results = json.loads(response['value'])
            # 确保结果是列表格式
            if isinstance(results, dict):
                results = [results]
            print(f"✅ 收到搜索结果: {len(results)} 条结果, 耗时: {elapsed_time:.2f}s")
            return jsonify({'results': results})
        except Exception as e:
            print(f"❌ 解析搜索结果失败: {e}")
            # 返回模拟数据作为备选
            results = create_mock_results(keyword)
            return jsonify({'results': results})
    
    # 如果TCP服务器无响应，返回模拟数据
    print(f"⚠️ TCP服务器无响应，返回模拟结果，耗时: {elapsed_time:.2f}s")
    results = create_mock_results(keyword)
    return jsonify({'results': results})

@app.route('/health')
def health_check():
    """健康检查端点"""
    client = get_tcp_client()
    if client and client.connected:
        return jsonify({
            'status': 'healthy', 
            'tcp_connected': True,
            'message': 'TCP服务器连接正常'
        })
    else:
        return jsonify({
            'status': 'unhealthy', 
            'tcp_connected': False,
            'message': 'TCP服务器连接失败，使用模拟数据'
        }), 503

if __name__ == '__main__':
    # 在启动时测试TCP连接
    print("🚀 正在初始化TCP客户端...")
    client = get_tcp_client()
    if client:
        print("✅ TCP客户端初始化成功")
    else:
        print("⚠️ TCP客户端初始化失败 - 将使用模拟数据")
    
    # 启动Flask应用
    print("🌐 启动HTTP网关服务器...")
    print("📍 访问 http://192.168.7.185:5000 使用搜索功能")
    print("📍 或者访问 http://127.0.0.1:5000 (本地)")
    try:
        app.run(host='0.0.0.0', port=5000, debug=True)
    except KeyboardInterrupt:
        print("\n👋 服务器已关闭")
        if client:
            client.close()